下半部是要介紹我們在現在的blog或是cms系統上很流行的tag功能。
沒有錯,鐵人賽的編輯器也有這個功能。
(坦白說我覺得除了不能預覽還有支援markdown之外,鐵人賽的編輯器不會到難用啊XD)
這裡有分成兩種做法,一種是使用gem,一種是自己刻一個。
第一種當然是快速很多,但是你在遇到問題或是想要客制化的時候還是得去看doc,
否則你會不知道到底發生什麼事情。
第二種自刻,並不是指寫出來的是毫無架構的爛code,
而是參考網路上其他人解法再自己去寫ruby code,比起open source的專案可能沒有那麼包山包海,
但也因為這樣你幾乎能掌握所有的東西,要加東西的話也很簡單。
acts-as-taggable-on這個gem遇到一點問題,
不過我還是將使用過程記錄下來,
想要直接看手作部分的可以跳到下方第一部份。
如果你看到下方參考影片的,提醒一下acts-as-taggable-on有做了一些更新,
所以有些指令會跟影片中的不太一樣,
在使用acts-as-taggable-on會遇到一個奇怪的bugs,所以用到一半就中斷了,
如果有興趣一起討論這個問題的可以再說,
想看功能實作的就直接看第一部分就好。
這個功能其實並不複雜,所以可以直接自己來就好
首先要先建立tag和tagging的model
rails g model tag name
rails g model tagging tag:belongs_to article:belongs_to
rake db:migrate
在post的model裡面加入使用tags的方法
因為tag可以給很多篇posts用、而一篇post也可以有很多個tags,這是一個many_to_many的關係,所以我們需要tagging來做資料表的關聯(這個應該可以另外開一篇說了)
def self.tagged_with(name)
Tag.find_by_name!(name).posts
end
def self.tag_counts
Tag.select("tags.*, count(taggings.tag_id) as count").
joins(:taggings).group("taggings.tag_id")
end
def tag_list
tags.map(&:name).join(", ")
end
def tag_list=(names)
self.tags = names.split(",").map do |n|
Tag.where(name: n.strip).first_or_create!
end
end
記得在posts controller裡面設定strong parameter
在index action加入這一段,讓我們借由tag來取得po文
def index
if params[:tag]
@posts = Post.tagged_with(params[:tag])
else
@posts = Post.all
end
end
再來就是加入tag和連結了:
get 'tags/:tag', to: 'posts#index', as: :tag
<%= raw post.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %>
post.tags.map(&:name)
會把同一個post底下的每個tag的名字塞進去array裡面,來看個例子 # 假設post底下有a, b, c三個tag,它們的name分別是 "a", "b", "c"
post.tags.map(&:name)
# 會回傳 ["a", "b", "c"] 這個陣列
post.tags.pluck(:name)
link\_to
helper之後,在用','去分開他們參考資料:
http://www.ruby-doc.org/core-2.1.3/Array.html#method-i-map
http://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html
http://railscasts.com/episodes/382-tagging
http://blog.endpoint.com/2012/05/instance-variable-collision-with.html
參考資料: